

#include <display_priv.h>

DISPLAY_Ctrl gDISPLAY_ctrl;

int DISPLAY_tskCreate( DISPLAY_CreatePrm *prm)
{
  int status, i;

  gDISPLAY_ctrl.blankDetectThres = 60;
  
  memset(&gDISPLAY_ctrl.chInfo, 0, sizeof(gDISPLAY_ctrl.chInfo));
  
  gDISPLAY_ctrl.pCaptureInfo = prm->captureInfo;
  if(gDISPLAY_ctrl.pCaptureInfo==NULL)
    return OSA_EFAIL;
    
  status = DISPLAY_v4l2Create(prm->displayMode, &gDISPLAY_ctrl.frameInfo);
  if(status!=OSA_SOK)
    return status;
    
  DISPLAY_layoutInit(); 
  
  for(i=0; i<gDISPLAY_ctrl.pCaptureInfo->chList.numCh; i++)
    gDISPLAY_ctrl.chInfo[i].curBufId = -1;

  return status;  
}

int DISPLAY_tskDelete( )
{
  int status;
  
  status = DISPLAY_v4l2Delete();
  
  return status;
}

int DISPLAY_getCaptureChIds()
{
  int i, bufId;
  
  // get newest channel data for display  
  for(i=0; i<gDISPLAY_ctrl.pCaptureInfo->chList.numCh; i++)
  {
    bufId = -1;
    OSA_queGet(&gDISPLAY_ctrl.pCaptureInfo->displayQue[i], &bufId, OSA_TIMEOUT_NONE);
    
    if(bufId != -1) {
      
      // got new buffer
      
      // release current buffer
      if(gDISPLAY_ctrl.chInfo[i].curBufId != -1) {
        MCVIP_putBuf( gDISPLAY_ctrl.pCaptureInfo->mcvipHndl, gDISPLAY_ctrl.chInfo[i].curBufId, MCVIP_FLAG_DISPLAY_DONE);
      }
      
      gDISPLAY_ctrl.chInfo[i].curBufId = bufId;
      gDISPLAY_ctrl.chInfo[i].blankCount = 0;
      
//      OSA_printf(" Display Ch %d: Buf %d\n", i, bufId);
      
    } else {
      #if 1
      gDISPLAY_ctrl.chInfo[i].blankCount++;
      if(gDISPLAY_ctrl.chInfo[i].blankCount >= gDISPLAY_ctrl.blankDetectThres)
      {
        // no video detected, release current buffer, show blank video in display
                
        gDISPLAY_ctrl.chInfo[i].blankCount = gDISPLAY_ctrl.blankDetectThres;
        
        if(gDISPLAY_ctrl.chInfo[i].curBufId != -1) {
          MCVIP_putBuf( gDISPLAY_ctrl.pCaptureInfo->mcvipHndl, gDISPLAY_ctrl.chInfo[i].curBufId, MCVIP_FLAG_DISPLAY_DONE);
        }
        
        gDISPLAY_ctrl.chInfo[i].curBufId = -1;          
      }
      #endif
    }
  }

  return OSA_SOK;
}

int DISPLAY_tskStartRun(OSA_TskHndl *pTsk, OSA_MsgHndl *pMsg, Bool *isDone, Bool *doAckMsg )
{
  int status;
  Bool done = FALSE, ackMsg = TRUE,nextPage = FALSE;
  Uint16 cmd;
  DISPLAY_BufInfo displayBufInfo;

  *isDone = FALSE;
  *doAckMsg = FALSE;
  
  status = DISPLAY_v4l2Start();
  
  OSA_tskAckOrFreeMsg(pMsg, status);  
  
  if(status != OSA_SOK) {
    return status;
  }
  
  while(!done) {
  
    DISPLAY_v4l2GetBuf( &displayBufInfo );
    
//    OSA_printf(" DISP %d \n", displayBufInfo.id);

    DISPLAY_getCaptureChIds();
    
    DISPLAY_layoutRun( &displayBufInfo,nextPage); 

    nextPage = FALSE;   
    
    DISPLAY_v4l2PutBuf( &displayBufInfo );  
    
    status = OSA_tskCheckMsg(pTsk, &pMsg);
    if(status==OSA_SOK) {
    
      cmd = OSA_msgGetCmd(pMsg);  
    
      switch(cmd) {
        case DISPLAY_CMD_STOP:
          done = TRUE;
          ackMsg = TRUE;
          break;
          
        case DISPLAY_CMD_DELETE:
          done = TRUE;
          *isDone = TRUE;
          *doAckMsg = TRUE;
          break;   

        case DISPLAY_CMD_NEXTPAGE:
          nextPage = TRUE; 
          OSA_tskAckOrFreeMsg(pMsg, OSA_SOK); 
          break;
                     
        default:   
          OSA_tskAckOrFreeMsg(pMsg, OSA_SOK);
          break;              
      }    
    }
  }

  DISPLAY_v4l2Stop();        
  if(ackMsg)
    OSA_tskAckOrFreeMsg(pMsg, OSA_SOK);          
  
  return status;
}

int DISPLAY_tskMain(struct OSA_TskHndl *pTsk, OSA_MsgHndl *pMsg, Uint32 curState )
{
  int status;
  Bool done = FALSE, ackMsg=FALSE;;
  Uint16 cmd = OSA_msgGetCmd(pMsg);
  DISPLAY_CreatePrm *pCreatePrm = (DISPLAY_CreatePrm*)OSA_msgGetPrm(pMsg);
  
  if( cmd != DISPLAY_CMD_CREATE || pCreatePrm==NULL) {
    OSA_tskAckOrFreeMsg(pMsg, OSA_EFAIL);
    return OSA_SOK;
  }
  
  status = DISPLAY_tskCreate( pCreatePrm );
  
  OSA_tskAckOrFreeMsg(pMsg, status);  
  
  if(status != OSA_SOK)
    return OSA_SOK;
  
  while(!done)
  {
    status = OSA_tskWaitMsg(pTsk, &pMsg);
    if(status != OSA_SOK) {
      done = TRUE;
      break;
    }
      
    cmd = OSA_msgGetCmd(pMsg);  
    
    switch(cmd) {
      case DISPLAY_CMD_START:
        DISPLAY_tskStartRun(pTsk, pMsg, &done, &ackMsg);      
        break;
        
      case DISPLAY_CMD_DELETE:
        done = TRUE;        
        ackMsg = TRUE;
        break;   
                   
      default:   
        OSA_tskAckOrFreeMsg(pMsg, OSA_SOK);
        break;              
    }
  }

  DISPLAY_tskDelete();
  if(ackMsg)
    OSA_tskAckOrFreeMsg(pMsg, OSA_SOK);          

  return OSA_SOK;
}


int DISPLAY_sendCmd(Uint16 cmd, void *prm, Uint16 flags )
{
  return OSA_mbxSendMsg(&gDISPLAY_ctrl.tskHndl.mbxHndl, &gDISPLAY_ctrl.mbxHndl, cmd, prm, flags);
}

int DISPLAY_create(DISPLAY_CreatePrm *prm)
{
  int status;
 
  status = OSA_tskCreate( &gDISPLAY_ctrl.tskHndl, DISPLAY_tskMain, DISPLAY_THR_PRI, DISPLAY_STACK_SIZE, 0);

  OSA_assertSuccess(status);
    
  status = OSA_mbxCreate( &gDISPLAY_ctrl.mbxHndl);  
  
  OSA_assertSuccess(status);  

  status = DISPLAY_sendCmd(DISPLAY_CMD_CREATE, prm, OSA_MBX_WAIT_ACK );
  
  return status;  
}

int DISPLAY_delete()
{
  int status;
  
  status = DISPLAY_sendCmd(DISPLAY_CMD_DELETE, NULL, OSA_MBX_WAIT_ACK );
  
  status = OSA_tskDelete( &gDISPLAY_ctrl.tskHndl );

  OSA_assertSuccess(status);
    
  status = OSA_mbxDelete( &gDISPLAY_ctrl.mbxHndl);  
  
  OSA_assertSuccess(status);  
  
  return status;
}

int DISPLAY_start()
{
  return DISPLAY_sendCmd(DISPLAY_CMD_START, NULL, OSA_MBX_WAIT_ACK );
}

int DISPLAY_stop()
{
  return DISPLAY_sendCmd(DISPLAY_CMD_STOP, NULL, OSA_MBX_WAIT_ACK );
}

int DISPLAY_nextPage()
{
  return DISPLAY_sendCmd(DISPLAY_CMD_NEXTPAGE, NULL, OSA_MBX_WAIT_ACK );
}


